package com.fly.tcp;

import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.WebAsyncTask;

import com.fly.core.JsonResult;
import com.fly.core.utils.JsonBeanUtils;
import com.fly.tcp.base.InitManager;
import com.fly.tcp.entity.Command;
import com.fly.tcp.service.ResultCallBack;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Api(tags = "tcp应用接口")
@RestController
@RequestMapping("/tcp")
public class DemoController
{
    @Autowired
    InitManager initManager;
    
    @Autowired
    ResultCallBack resultCallBack;
    
    @Autowired
    ThreadPoolTaskExecutor executor;
    
    @ApiOperation("client发消息")
    @ApiImplicitParam(name = "msg", example = "忽如一夜春风来", required = true)
    @PostMapping("/client/sendMsg")
    public JsonResult<String> sendMsgFromClient(String msg)
    {
        initManager.getClient().sendMsg(msg);
        return JsonResult.success(msg, "业务处理成功");
    }
    
    /**
     * 客户端业务处理结果更多是通过回调实现的
     * 
     * @param cmd
     * @return
     * @throws IOException
     */
    @ApiOperation("server发消息Callable")
    @ApiImplicitParam(name = "msg", example = "千树万树梨花开", required = true)
    @PostMapping("/server/sendMsg/callable")
    public Callable<JsonResult<?>> sendMsgFromServer01(String msg)
        throws IOException
    {
        return () -> {
            Command command = new Command().setClientId(initManager.getClient().getClientName()).setText(msg);
            initManager.getServer().sendMsg(initManager.getClient().getClientName(), JsonBeanUtils.beanToJson(command));
            
            int index = 0;
            String result = resultCallBack.queryResult(command.getCommandId());
            while (StringUtils.isBlank(result) && index++ < 100)
            {
                TimeUnit.MILLISECONDS.sleep(20);
                result = resultCallBack.queryResult(command.getCommandId());
            }
            return StringUtils.isNotBlank(result) ? JsonResult.success(result, "业务处理成功") : JsonResult.error("响应超时，请重试");
        };
    }
    
    /**
     * 客户端业务处理结果更多是通过回调实现的(WebAsyncTask升级版callable，增加超时异常等处理)
     * 
     * @param cmd
     * @return
     * @throws IOException
     */
    @ApiOperation("server发消息webAsyncTask")
    @ApiImplicitParam(name = "msg", example = "千树万树梨花开", required = true)
    @PostMapping("/server/sendMsg/webAsyncTask")
    public WebAsyncTask<JsonResult<?>> sendMsgFromServer02(String msg)
        throws IOException
    {
        WebAsyncTask<JsonResult<?>> webAsyncTask = new WebAsyncTask<>(2000L, executor, () -> {
            Command command = new Command().setClientId(initManager.getClient().getClientName()).setText(msg);
            initManager.getServer().sendMsg(initManager.getClient().getClientName(), JsonBeanUtils.beanToJson(command));
            
            int index = 0;
            String result = resultCallBack.queryResult(command.getCommandId());
            while (StringUtils.isBlank(result) && index++ < 100)
            {
                TimeUnit.MILLISECONDS.sleep(20);
                result = resultCallBack.queryResult(command.getCommandId());
            }
            return StringUtils.isNotBlank(result) ? JsonResult.success(result, "业务处理成功") : JsonResult.error("响应超时，请重试");
        });
        webAsyncTask.onCompletion(() -> log.info("调用完成"));
        webAsyncTask.onError(() -> JsonResult.error("业务处理出错"));
        webAsyncTask.onTimeout(() -> JsonResult.error("业务处理超时"));
        return webAsyncTask;
    }
    
    /**
     * 客户端业务处理结果更多是通过回调实现的
     * 
     * @param cmd
     * @return
     * @throws IOException
     * @throws TimeoutException
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @ApiOperation("server发消息")
    @ApiImplicitParam(name = "msg", example = "千树万树梨花开", required = true)
    @PostMapping("/server/sendMsg")
    public DeferredResult<String> sendMsgFromServer(String msg)
        throws IOException, InterruptedException, ExecutionException, TimeoutException
    {
        String clientName = initManager.getClient().getClientName();
        Command command = new Command().setClientId(clientName).setText(msg);
        initManager.getServer().sendMsg(clientName, JsonBeanUtils.beanToJson(command));
        
        // 异步返回结果
        DeferredResult<String> deferredResult = new DeferredResult<>(2000L, "调用超时");
        // deferredResult.onCompletion(() -> log.info("调用完成"));
        // deferredResult.onTimeout(() -> deferredResult.setResult("调用超时"));
        resultCallBack.processResult(deferredResult, command.getCommandId());
        return deferredResult;
    }
}
